package pl.drypisy;

import java.awt.image.BufferedImage;

/**
 * 
 * @author Drobny
 */
public class RotationProcess extends ImageProcess {
    private double angle,angleRadian;
    private int rotationCenterX, rotationCenterY;
    private BufferedImage src;

    public void setParams(int angle, int rCenterX, int rCenterY) {
        this.angle=angle;
        this.angleRadian=(double)(2*Math.PI*angle)/360;
        this.rotationCenterX=rCenterX;
        this.rotationCenterY=rCenterY;
    }

    @Override
    public BufferedImage process(BufferedImage image) {
        this.src = image;
        srcWidth = src.getWidth();
        srcHeight = src.getHeight();
        if(angle==0){
            System.out.println("angle 0 "+ angle);
            return image;
        } else if(angle==90){
            //return rotation90();
        } else if(angle==180){
            //return rotation180();
        }
        
        double sinVal=Math.sin(angleRadian);
        double cosVal=Math.cos(angleRadian);
        double p1x=-srcHeight*sinVal;
        double p1y=srcHeight*cosVal;
        double p2x=srcWidth*cosVal - srcHeight*sinVal;
        double p2y=srcHeight*cosVal + srcWidth*sinVal;
        double p3x=srcWidth*cosVal;
        double p3y=srcWidth*sinVal;
        double minX=Math.min(0, Math.min(p1x, Math.min(p2x, p3x)));
        double minY=Math.min(0, Math.min(p1y, Math.min(p2y, p3y)));
        double maxX=Math.max(p1x, Math.max(p2x, p3x));
        double maxY=Math.max(p1y, Math.max(p2y, p3y));
        maxX=Math.abs(maxX);
        maxY=Math.abs(maxY);
        int width=(int) Math.ceil(maxX-minX);
        int height=(int) Math.ceil(maxY-minY);
        
        BufferedImage dest = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        int[] outPixels = new int[width] ;
        int[] inPixels = src.getRGB(0, 0, srcWidth, srcHeight, null, 0, srcWidth);
        double out[] = new double[2];
        int nw, ne, sw, se;

        for (int y=0;y<height;y++) {
            for (int x=0;x<width;x++) {
                getOriginalCoordinates((int)(x + minX), (int)(y + minY),out);
                int srcX = (int)Math.floor( out[0] );
                int srcY = (int)Math.floor( out[1] );
                int pix;
                if(doInterpolation) {
                    double xWeight = out[0]-srcX;
                    double yWeight = out[1]-srcY;
                    nw = getPixel( inPixels, srcX, srcY, srcWidth, srcHeight);
                    ne = getPixel( inPixels, srcX+1, srcY, srcWidth, srcHeight );
                    sw = getPixel( inPixels, srcX, srcY+1, srcWidth, srcHeight );
                    se = getPixel( inPixels, srcX+1, srcY+1, srcWidth, srcHeight );
                    pix = bilinearInterpolation(xWeight, yWeight,  nw, ne, sw, se);
                }
                else pix = getPixel(inPixels,srcX,srcY,srcWidth,srcHeight);
                outPixels[x] = pix;
            }
            dest.setRGB(0, y, width, 1, outPixels, 0, height);
        }
        return dest;
    }


    @Override
    protected void getOriginalCoordinates(int x, int y, double out[]) {
        out[0]=Math.cos(angleRadian)*(x-rotationCenterX) + Math.sin(angleRadian)*(y-rotationCenterY) + rotationCenterX;
        out[1]=Math.cos(angleRadian)*(y-rotationCenterY) - Math.sin(angleRadian)*(x-rotationCenterX) + rotationCenterY;
        //out[0]=Math.cos(angleRadian)*(x) + Math.sin(angleRadian)*(y);
        //out[1]=-Math.sin(angleRadian)*(x) + Math.cos(angleRadian)*(y);
    }
    
    /*private BufferedImage rotation90(){
        int width=srcHeight;
        int height=srcWidth;
        BufferedImage dest = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        int[] outPixels = new int[width] ;
        int[] inPixels = src.getRGB(0, 0, srcWidth, srcHeight, null, 0, srcWidth);
        double out[] = new double[2];
        int nw, ne, sw, se;
        setInterpolate(true);
        for (int y=0;y<height;y++) {
            for (int x=0;x<width;x++) {
                out[0]=y;
                out[1]=srcWidth/2-1-x;
                int srcX = (int)Math.floor( out[0] );
                int srcY = (int)Math.floor( out[1] );
                int pix;
                if(doInterpolation) {
                    double xWeight = out[0]-srcX;
                    double yWeight = out[1]-srcY;
                    nw = getPixel( inPixels, srcX, srcY, srcWidth, srcHeight);
                    ne = getPixel( inPixels, srcX+1, srcY, srcWidth, srcHeight );
                    sw = getPixel( inPixels, srcX, srcY+1, srcWidth, srcHeight );
                    se = getPixel( inPixels, srcX+1, srcY+1, srcWidth, srcHeight );
                    pix = bilinearInterpolation(xWeight, yWeight,  nw, ne, sw, se);
                }
                else pix = getPixel(inPixels,srcX,srcY,srcWidth,srcHeight);
                outPixels[x] = pix;
            }
            dest.setRGB(0, y, width, 1, outPixels, 0, height);
        }
        return dest;
    }
    
    private BufferedImage rotation180(){
        int width=srcWidth;
        int height=srcHeight;
        BufferedImage dest = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        int[] outPixels = new int[width] ;
        int[] inPixels = src.getRGB(0, 0, srcWidth, srcHeight, null, 0, srcWidth);
        double out[] = new double[2];
        int nw, ne, sw, se;
        setInterpolate(true);
        for (int y=0;y<height;y++) {
            for (int x=0;x<width;x++) {
                out[0]=x;
                out[1]=srcHeight-1-y;
                int srcX = (int)Math.floor( out[0] );
                int srcY = (int)Math.floor( out[1] );
                int pix;
                if(doInterpolation) {
                    double xWeight = out[0]-srcX;
                    double yWeight = out[1]-srcY;
                    nw = getPixel( inPixels, srcX, srcY, srcWidth, srcHeight);
                    ne = getPixel( inPixels, srcX+1, srcY, srcWidth, srcHeight );
                    sw = getPixel( inPixels, srcX, srcY+1, srcWidth, srcHeight );
                    se = getPixel( inPixels, srcX+1, srcY+1, srcWidth, srcHeight );
                    pix = bilinearInterpolation(xWeight, yWeight,  nw, ne, sw, se);
                }
                else pix = getPixel(inPixels,srcX,srcY,srcWidth,srcHeight);
                outPixels[x] = pix;
            }
            dest.setRGB(0, y, width, 1, outPixels, 0, height);
        }
        return dest;
    }
    */
}